

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Random;

import javax.swing.DefaultFocusManager;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;

@SuppressWarnings("serial")
public class MgBoard extends JPanel implements ActionListener,MgCommon{
	private MgPlayer player;
	private Timer timer = new Timer(50, this);//Refreshes the screen.
	private Image background = (new ImageIcon("minigameBackground.jpg")).getImage();
	private Image playerImage = (new ImageIcon("Player.png")).getImage();
	private Image playerHurtImage = (new ImageIcon("PlayerHurt.png")).getImage();
	
	private Image soldierImage = (new ImageIcon("Soldier.png")).getImage();
	private Image soldierHurtImage = (new ImageIcon("SoldierHurt.png")).getImage();

	private final int enemySpawnTimeBase = 3000;
	private final int enemySpawnTimeRange = enemySpawnTimeBase;
	private Timer enemySpawnTimer = new Timer(enemySpawnTimeBase, this);//Spawns a new enemy.
	
	private boolean gameover = false;
	private boolean victory = false;
	
	int width,height;
	Party party;
	int enemyCount;
	LinkedList<MgSoldier> soldiersToAdd = new LinkedList<MgSoldier>();
	MainCardPanel display;
	int deadIndex=-1;
	ArrayList<Member> newTravellers;
	
	public MgBoard(int width,int height, Party party, MainCardPanel display){
		//Clear all MgCommon variables;
		projectiles.clear();
		projectilesToRemove.clear();
		fighters.clear();//The first in fighters is always the player.
		fightersToRemove.clear();
		
		enemyCount = 7;
		this.display = display;
		this.width = width;
		this.height = height;
		this.party=party;
		newTravellers = party.getTravellers();
		setSize(width, height);
		KeyEventDispatcher myKeyEventDispatcher = new DefaultFocusManager();
		KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(myKeyEventDispatcher);
		
		int initX=width/2,initY=height/2;
		player = new MgPlayer(width, height, initX, initY, playerImage,playerHurtImage,null,party.getAmmunition());
		player.reload();
		player.setMovement(5);
		fighters.add(player);
		for(int i=0;i<enemyCount;i++){
			soldiersToAdd.add(new MgSoldier(0, 0, 200, soldierImage, soldierHurtImage,new MgWeapon(2,20,1,200,2000,10,Color.red)));
		}
		addKeyListener(new AL());
		setFocusable(true);
		timer.setActionCommand("refresh");
		enemySpawnTimer.setActionCommand("enemy");
		timer.start();
		enemySpawnTimer.start();
		
		repaint();
	}
	
	/**
	 * Triggered by the Timer. All update actions go here.
	 */
	public void actionPerformed(ActionEvent e){
		if(e.getActionCommand().equals("enemy")){
			if(!soldiersToAdd.isEmpty()){
				Random gen = new Random();
				int side = gen.nextInt(4);
				int x = width;
				int y = 0;
				if(side==0){
					x = 0;//-soldierImage.getWidth(null);
					y = gen.nextInt(height);
				}else if(side==1){
					x = gen.nextInt(width);
					y = 0;//-soldierImage.getHeight(null);
				}else if(side==2){
					x = width-soldierImage.getWidth(null);
					y = gen.nextInt(height);
				}else if(side==3){
					x = gen.nextInt(width);
					y = height-soldierImage.getHeight(null);
				}
				MgSoldier addedSoldier = soldiersToAdd.poll();
				addedSoldier.setX(x);
				addedSoldier.setY(y);
				fighters.add(addedSoldier);
				enemySpawnTimer.setDelay(gen.nextInt(enemySpawnTimeRange)+enemySpawnTimeBase);
				enemySpawnTimer.start();
			}else if(fighters.size()==1 && fighters.get(0)==player){
				victory=true;
			}
		}
		
		if(e.getActionCommand().equals("refresh")){
			for(MgFighter each:fighters){
				each.move();
				each.fire();
			}
			for(MgProjectile each:projectiles){
				each.move();
			}
			for(MgFighter fighter:fighters){
				int left;
				int right;
				int top;
				int bottom;
				left = fighter.getX()-fighter.getWidth()/2;
				right = fighter.getX()+fighter.getWidth()/2;
				top = fighter.getY()-fighter.getHeight()/2;
				bottom = fighter.getY()+fighter.getHeight()/2;
				if(!fighter.equals(player)){
					if(player.getX()<=right && player.getX()>=left && player.getY()>=top && player.getY()<=bottom){
						if(!fighter.hurt(player.getMeleeDamage())){
							fightersToRemove.add(fighter);
						}
						if(!player.hurt(fighter.getMeleeDamage())){
							gameover=true;
							repaint();
						}
					}
				}

				for(MgProjectile each:projectiles){
					if(each!=null){
						if(each.getX()<=0 || each.getX()>=width || each.getY()<=0 || each.getY()>=height){
							projectilesToRemove.add(each);
						}else{
							if(each.getX()<=right && each.getX()>=left && each.getY()>=top && each.getY()<=bottom){
								projectilesToRemove.add(each);
								if(!fighter.hurt(each.getDamage())){
									fightersToRemove.add(fighter);
									if(fighter.equals(player)){
										gameover = true;
										repaint();
									}
								}
							}
						}
					}
				}
			}
			for(MgProjectile each:projectilesToRemove){
				projectiles.remove(each);
			}
			projectilesToRemove.clear();
			for(MgFighter each:fightersToRemove){
				fighters.remove(each);
			}
			fightersToRemove.clear();
			repaint();
		}
	}
	
	public void paint(Graphics g){
		super.paint(g);
		Graphics2D g2d = (Graphics2D)g;
		g2d.setFont(new Font("Arial", Font.PLAIN, 12));
		g2d.drawImage(background,0,0,null);

		if(gameover){
			Random gen = new Random();
			deadIndex = gen.nextInt(party.getTravellers().size());
		    g2d.setFont(new Font("Arial", Font.PLAIN, 30));
			//g2d.drawString("Defeat! "+newTravellers.get(deadIndex).getName()+" was killed. Press ENTER to continue.", height/2-50, width/2-100);
			g2d.drawString("Defeat! Press ENTER to continue.", height/2-50, width/2-100);
			g2d.setFont(new Font("Arial", Font.PLAIN, 12));
			timer.stop();
		}else if(victory){
		    g2d.setFont(new Font("Arial", Font.PLAIN, 30));
			g2d.drawString("Victory! Press ENTER to continue.", height/2-50, width/2-100);
			g2d.setFont(new Font("Arial", Font.PLAIN, 12));
		}
		g2d.drawImage(player.getImage(),player.getX()-player.getImage().getWidth(null)/2,player.getY()-player.getImage().getHeight(null)/2,null);
		
		//Start status display
		g2d.drawString(player.getWeapon().getClip()+"/"+player.getWeapon().getMaxCapacity()+" Ammo: "+player.getAmmo()+"   Ammo used per shot: "+player.getWeapon().getConsumptionRate(), 10, 20);
		g2d.drawString("Health: "+player.getHealth()+"/"+player.getMaxHealth(), 10, 35);
		g2d.drawString("Press W,A,S,D to move. Press E to reload. Press spacebar to fire.", width/2, 20);
		g2d.drawString("If you are out of ammo, melee attack by running into the enemy. Or make them shoot each other!", width/2, 35);

		if(player.getHealth()>0){
			g2d.setColor(Color.green);
			g2d.fillRect(10,40, 100*player.getHealth()/player.getMaxHealth(), 10);
			g2d.setColor(Color.red);
			g2d.fillRect(10+100*player.getHealth()/player.getMaxHealth(),40, 100-100*player.getHealth()/player.getMaxHealth(), 10);
		}else{
			g2d.setColor(Color.red);
			g2d.fillRect(10,40, 100, 10);
		}
		//End status display
		
		for(MgProjectile each:projectiles){
			g2d.setColor(each.getColor());
			g2d.fillRect(each.getX()-each.getSize()/2, each.getY()-each.getSize()/2, each.getSize(), each.getSize());
		}
		for(MgFighter each:fighters){
			if(!each.equals(player)){
				int barLength = 50;
				int barHeight = 10;
				g2d.drawImage(each.getImage(),each.getX()-each.getImage().getWidth(null)/2,each.getY()-each.getImage().getHeight(null)/2,null);
				g2d.setColor(Color.green);
				g2d.fillRect(each.getX()-barLength/2,each.getY()-each.getHeight()/2-barHeight, barLength*each.getHealth()/each.getMaxHealth(), barHeight);
				g2d.setColor(Color.red);
				g2d.fillRect(each.getX()-barLength/2+barLength*each.getHealth()/each.getMaxHealth(),each.getY()-each.getHeight()/2-barHeight, barLength-barLength*each.getHealth()/each.getMaxHealth(), barHeight);
			}
		}
		/*
		g2d.drawImage(img,width*(int)Math.ceil(((double)player.getX())/width)+player.getInitX()-player.getX(),0,null);
		g2d.drawImage(img,width*(int)Math.floor(((double)player.getX())/width)+player.getInitX()-player.getX(),0,null);
		g2d.drawImage(img,width*((int)Math.floor(((double)player.getX())/width)-1)+player.getInitX()-player.getX(),0,null);
		g2d.drawImage(player.getImage(),player.getInitX(),(int)Math.round(player.getY()),null);
		*/
	}
	
	private class AL extends KeyAdapter{
		public void keyReleased(KeyEvent e){
			player.keyReleased(e);
		}
		public void keyPressed(KeyEvent e){
			if((gameover || victory) && e.getKeyCode() == KeyEvent.VK_ENTER){
				party.setAmmunition(player.getAmmo()+player.getClip());
				if(deadIndex>0){
					newTravellers.get(deadIndex).setAlive(false);
					newTravellers.get(deadIndex).setHealth(0);
					party.setTravellers(newTravellers);
				}
				display.userRespondedToRandomEvent();
			}else
				player.keyPressed(e);
		}
	}
}
